/*
 * $Id: timer.h 315 2010-03-25 23:57:03Z cmtonkinson@gmail.com $
 *
 * This file is part of the Symphony project <http://code.google.com/p/symphonymud/>
 * Copyright 2005-2010 Chris Tonkinson <cmtonkinson@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef H_SYMPHONY_TIMER
#define H_SYMPHONY_TIMER

/*
 * _lower must be set to a non-negative integer.  _upper is optional.  If
 * _upper is greater than _lower, then the value of _when will be set,
 * pseudorandomly (using rand()), between _lower and _upper seconds in the
 * future.  If _upper is not given (or is less than _lower), then _when
 * will be set to _lower seconds in the future.
 *
 * --== Examples ==--
 *  Values:
 *   _lower = 10
 *   _upper = 0;
 *  Result:
 *   _when will be set to 10 seconds in the future.
 *
 *  Values:
 *   _lower = 10
 *   _upper = 20
 *  Result:
 *   _when will be set between 10 and 20 seconds in the future (using rand()).
 */

#include <ctime>
#include <string>
#include "estring.h"



class Timer {
  private:
    bool                  _enabled; // Whether or not this timer should fire.
    time_t                _when;    // When the timer is due to fire again.
    unsigned long         _lower;   // See comments above.
    unsigned long         _upper;   // See comments above.
    unsigned long         _times;   // The number of times left to fire (0 means stop firing; negative means fire indefinitely).
    std::string           _name;    // The verbose name of the timer; used for reporting.
    emap                  _data;    // Any additional state a timer may need to keep.

  public:
    // Constructors...
    Timer( void );
    virtual ~Timer( void );

    // Operators...
    bool                  operator < ( Timer* timer )         { return ( this->when() > timer->when() ); }

    // Accessor methods...
    void                  enabled( const bool& enabled )      { _enabled = enabled; }
    bool                  enabled( void ) const               { return _enabled; }
    void                  when( const time_t& when )          { _when = when; }
    time_t                when( void ) const                  { return _when; }
    void                  lower( const unsigned long& lower ) { _lower = lower; }
    unsigned long         lower( void ) const                 { return _lower; }
    void                  upper( const unsigned long& upper ) { _upper = upper; }
    unsigned long         upper( void ) const                 { return _upper; }
    void                  times( const unsigned long& times ) { _times = times; }
    unsigned long         times( void ) const                 { return _times; }
    void                  name( const std::string& name )     { _name = name; }
    virtual std::string   name( void ) const                  { return _name; }
    emap&                 data( void )                        { return _data; }

    // General methods...
    void                  reset( void );
    bool                  ready( void );
    virtual bool          fire( void )                        = 0;
};



#define DEF_TIMER(NAME)             \
class NAME: public Timer {          \
  public:                           \
    NAME( void );                   \
    virtual ~NAME( void );          \
                                    \
    virtual bool  fire( void );     \
};



DEF_TIMER(TmrAutosave)
DEF_TIMER(TmrTick)



/* special timer derivation for area resets only */
class TmrReset: public Timer {
  private:
    Area*                 _area;

  public:
    TmrReset( Area* area );
    virtual ~TmrReset( void );

    virtual std::string   name( void ) const;
    void                  area( Area* area )    { _area = area; }
    Area*                 area( void ) const    { return _area; }

    virtual bool          fire( void );
};



#endif // #ifndef H_SYMPHONY_TIMER

